package de.fstyle.test.spring.mvc.security;

import javax.annotation.Resource;
import javax.naming.NamingException;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({
		"file:src/main/webapp/WEB-INF/spring/security.xml",
		"file:src/main/webapp/WEB-INF/spring/application-context.xml",
		"file:src/main/webapp/WEB-INF/spring/servlet-context.xml"
		})
@ActiveProfiles({"test", "container"})
public class WebappTestEnvironment {

	@Resource
	private FilterChainProxy springSecurityFilterChain;
	
	@Autowired
	protected UserDetailsService userDetailsService;
	
	@Autowired
	private WebApplicationContext wac;

	protected MockMvc mockMvc;
	
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	protected UsernamePasswordAuthenticationToken getPrincipal(
			String username) {
		
		UserDetails user = 
				this.userDetailsService.loadUserByUsername(username);
		
		UsernamePasswordAuthenticationToken authentication =
				new UsernamePasswordAuthenticationToken(
						user, 
						user.getPassword(), 
						user.getAuthorities());

		return authentication;
	}
	
	protected MockSecurityContext getMockSecurityContext(String username) {
		return new MockSecurityContext(this.getPrincipal(username));
	}
	
	protected MockHttpSession getMockSecurityContextSession(String username) {
		MockHttpSession session = new MockHttpSession();
		session.setAttribute(
				HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, 
				this.getMockSecurityContext(username));
		return session;
	}
	
	@Before
	public void setupMockMvc() throws NamingException {
		
		// setup mock MVC
		this.mockMvc = MockMvcBuilders
				.webAppContextSetup(this.wac)
				.addFilters(this.springSecurityFilterChain)
				.build();
	}
}
